package com.waiting.nio;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @Description
 * @Author bjweitingting
 * @Date 2018/10/18
 **/
public class NIOServer extends Thread {
    @Override
    public void run() {
        //try中创建selector和channel
        //1、 通过Selector.open()创建selector，作为类似调度员的角色；
        //2、创建ServerSocketChannel，并在selector中注册，通过指定SelectionKey.OP_ACCEPT，告诉调度员，关注的是连接请求；
        //   配置configureBlocking(false)为非阻塞模式
        try (Selector selector = Selector.open();
             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
             ServerSocketChannel serverSocketChannelTwo = ServerSocketChannel.open()) {
            serverSocketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
            serverSocketChannel.configureBlocking(false);
            //注册到selector，并说明关注点
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            //设置两个
            serverSocketChannelTwo.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8889));
            //设置channel工作在非阻塞模式下
            serverSocketChannelTwo.configureBlocking(false);
            //注册到selector，并说明关注点
            SelectionKey selectionKeyTmp = serverSocketChannelTwo.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("interest="+selectionKeyTmp.interestOps());
            while (true) {
                //selector阻塞在select(),当有channel发生连接请求时，就会被唤醒；
                selector.select();
                //返回发生连接请求的channel
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                System.out.println(selectionKeys.size());
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    System.out.println(selectionKey.readyOps());
                    //生产系统中一般要进行额外就绪状态检查
                    sayHello((ServerSocketChannel) selectionKey.channel());
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sayHello(ServerSocketChannel serverSocketChannel) {
        try (SocketChannel client = serverSocketChannel.accept()) {
            client.write(Charset.defaultCharset().encode("hello world"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NIOServer nioServer = new NIOServer();
        nioServer.start();
        try (Socket client = new Socket(InetAddress.getLocalHost(), 8888);
             Socket client2 = new Socket(InetAddress.getLocalHost(), 8888)) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            bufferedReader.lines().forEach(s -> System.out.println(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
